package com.nulldev.util.web.HttpServer3.util;

import java.io.IOException;
import java.io.OutputStream;

import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.VariableAPI.MathUtil;
import com.nulldev.util.data.Variables;
import com.nulldev.util.data.Charsets.CharsetUtil;

public class ChunkedOutputStream extends OutputStream {

	private static final byte[] CHUNK_EOF =
		{ '\r', '\n' };
	private static final boolean DO_FLUSH = false;

	private static byte[] MAKE_HEADER_FOR_LEN(final int length) {
		if (length < 0)
			throw new UnsupportedOperationException();
		return ArrayUtils.addAll(MathUtil.toHex(length).getBytes(CharsetUtil.US_ASCII), CHUNK_EOF);
	}

	private final OutputStream os;

	public ChunkedOutputStream(final OutputStream os) {
		this.os = Variables.requireNonNullObject(os, "os");
	}

	@Override
	public void write(final int b) throws IOException {
		os.write(MAKE_HEADER_FOR_LEN(1));
		os.write(b);
		os.write(CHUNK_EOF);
		if (DO_FLUSH)
			os.flush();
	}

	@Override
	public void write(final byte[] b) throws IOException {
		this.write(b, 0, b.length);
	}

	@Override
	public void write(final byte[] b, final int off, final int len) throws IOException {
		os.write(MAKE_HEADER_FOR_LEN(len));
		os.write(b, off, len);
		os.write(CHUNK_EOF);
		if (DO_FLUSH)
			os.flush();
	}

	public void writeEOF() throws IOException {
		os.write(MAKE_HEADER_FOR_LEN(0));
		os.write(CHUNK_EOF);
		if (DO_FLUSH)
			os.flush();
	}

	@Override
	public void close() throws IOException {
		os.close();
	}

	@Override
	public void flush() throws IOException {
		os.flush();
	}
}
